package com.egg.gateway.service;

import cn.hutool.core.util.ObjectUtil;
import com.egg.auth.feign.AuthUserFeignClient;
import com.egg.auth.model.LoginUserInfo;
import com.egg.basic.fegin.BasicSecureFeignClient;
import com.egg.common.core.exception.CustomException;
import com.egg.common.core.model.response.ResponseData;
import com.egg.common.swagger.param.child.SwaggerSecure;
import com.egg.common.swagger.param.child.SwaggerToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * 跨域
 *
 * @author east
 */
@Slf4j
@ComponentScan(basePackages = {"com.egg.auth.*", "com.egg.basic.*", "com.egg.common.swagger.param"})
@EnableFeignClients(basePackages = {"com.egg.auth.*", "com.egg.basic.*"})
@Component
public class FeignService {


    /*
        目前暂时没有解决, gateway 调用feignClient 传递请求头
        这里在调用feignClient, 目标客户端无法从请求头中获取获取请求信息
     */

    @Bean
    @ConditionalOnMissingBean
    public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
        //调用其他微服务报feign.codec.DecodeException 异常
        return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
    }


    @Resource(name = "contextFilterThreadPoolTaskExecutor")
    private ThreadPoolTaskExecutor contextFilterThreadPoolTaskExecutor;
    @Autowired
    private SwaggerToken swaggerToken;
    @Autowired
    private AuthUserFeignClient authUserFeignClient;
    @Autowired
    private SwaggerSecure swaggerSecure;
    @Autowired
    private BasicSecureFeignClient basicSecureFeignClient;


    /**
     * 异步查询用户信息
     *
     * @param request 当前请求
     * @return
     */
    public Future<LoginUserInfo> getLoginUserByToken(final ServerHttpRequest request) {
        if (null == request) {
            throw new CustomException("获取用户标识失败");
        }
        String token = request.getHeaders().getFirst(swaggerToken.getName());
        return getLoginUserByToken(token);
    }

    /**
     * 异步查询用户信息
     *
     * @param token 身份信息
     * @return
     */
    public Future<LoginUserInfo> getLoginUserByToken(String token) {
        if (ObjectUtil.isEmpty(token)) {
            throw new CustomException("请传入用户标识");
        }
        return CompletableFuture.supplyAsync(() -> {
            // 这里调用 权限服务
            ResponseData<LoginUserInfo> rd = authUserFeignClient.userLoginInfoByToken(token);
            if (rd.isSuccess()) {
                return rd.getData();
            } else {
                throw new CustomException(rd.getMsg());
            }
        }, contextFilterThreadPoolTaskExecutor);
    }

    /**
     * 异步查询用户信息
     *
     * @param request 当前请求
     * @return
     */
    public Future<Optional<String>> aes(final ServerHttpRequest request) {
        if (null == request) {
            return new AsyncResult<>(Optional.empty());
        }
        String secure = request.getHeaders().getFirst(swaggerSecure.getName());
        return aes(secure);
    }

    /**
     * 异步查询对称秘钥
     *
     * @return
     */
    public Future<Optional<String>> aes(String secure) {
        if (ObjectUtil.isEmpty(secure)) {
            return new AsyncResult<>(Optional.empty());
        }
        return CompletableFuture.supplyAsync(() -> {
            // 这里调用 权限服务
            ResponseData<String> rd = basicSecureFeignClient.aes(secure);
            if (rd.isSuccess()) {
                return Optional.ofNullable(rd.getData());
            }
            return Optional.empty();
        }, contextFilterThreadPoolTaskExecutor);
    }

}